// GENERATED - DO NOT EDIT
// Copyright 2018+ the Deno authors. All rights reserved. MIT license.
// https://raw.githubusercontent.com/denoland/deno/main/cli/tests/unit/webcrypto_test.ts
import { createDenoTest } from "deno:harness";
const { test, assert, assertEquals, assertNotEquals, assertRejects } = createDenoTest(import.meta.path);
test(async function testImportArrayBufferKey() {
    const subtle = window.crypto.subtle;
    assert(subtle);
    const key = new Uint8Array([
        1,
        2,
        3,
        4,
        5,
        6,
        7,
        8,
        9,
        10,
        11,
        12,
        13,
        14,
        15,
        16
    ]);
    const cryptoKey = await subtle.importKey("raw", key.buffer, {
        name: "HMAC",
        hash: "SHA-1"
    }, true, [
        "sign"
    ]);
    assert(cryptoKey);
    await subtle.sign({
        name: "HMAC"
    }, cryptoKey, new Uint8Array(8));
});
test(async function testSignVerify() {
    const subtle = window.crypto.subtle;
    assert(subtle);
    for (const algorithm of [
        "RSA-PSS",
        "RSASSA-PKCS1-v1_5"
    ]){
        for (const hash of [
            "SHA-1",
            "SHA-256",
            "SHA-384",
            "SHA-512"
        ]){
            const keyPair = await subtle.generateKey({
                name: algorithm,
                modulusLength: 2048,
                publicExponent: new Uint8Array([
                    1,
                    0,
                    1
                ]),
                hash
            }, true, [
                "sign",
                "verify"
            ]);
            const data = new Uint8Array([
                1,
                2,
                3
            ]);
            const signAlgorithm = {
                name: algorithm,
                saltLength: 32
            };
            const signature = await subtle.sign(signAlgorithm, keyPair.privateKey, data);
            assert(signature);
            assert(signature.byteLength > 0);
            assert(signature.byteLength % 8 == 0);
            assert(signature instanceof ArrayBuffer);
            const verified = await subtle.verify(signAlgorithm, keyPair.publicKey, signature, data);
            assert(verified);
        }
    }
});
const plainText = new Uint8Array([
    95,
    77,
    186,
    79,
    50,
    12,
    12,
    232,
    118,
    114,
    90,
    252,
    229,
    251,
    210,
    91,
    248,
    62,
    90,
    113,
    37,
    160,
    140,
    175,
    231,
    60,
    62,
    186,
    196,
    33,
    119,
    157,
    249,
    213,
    93,
    24,
    12,
    58,
    233,
    148,
    38,
    69,
    225,
    216,
    47,
    238,
    140,
    157,
    41,
    75,
    60,
    177,
    160,
    138,
    153,
    49,
    32,
    27,
    60,
    14,
    129,
    252,
    71,
    202,
    207,
    131,
    21,
    162,
    175,
    102,
    50,
    65,
    19,
    195,
    182,
    98,
    48,
    195,
    70,
    8,
    196,
    244,
    89,
    54,
    52,
    206,
    2,
    178,
    103,
    54,
    34,
    119,
    240,
    168,
    64,
    202,
    116,
    188,
    61,
    26,
    98,
    54,
    149,
    44,
    94,
    215,
    170,
    248,
    168,
    254,
    203,
    221,
    250,
    117,
    132,
    230,
    151,
    140,
    234,
    93,
    42,
    91,
    159,
    183,
    241,
    180,
    140,
    139,
    11,
    229,
    138,
    48,
    82,
    2,
    117,
    77,
    131,
    118,
    16,
    115,
    116,
    121,
    60,
    240,
    38,
    170,
    238,
    83,
    0,
    114,
    125,
    131,
    108,
    215,
    30,
    113,
    179,
    69,
    221,
    178,
    228,
    68,
    70,
    255,
    197,
    185,
    1,
    99,
    84,
    19,
    137,
    13,
    145,
    14,
    163,
    128,
    152,
    74,
    144,
    25,
    16,
    49,
    50,
    63,
    22,
    219,
    204,
    157,
    107,
    225,
    104,
    184,
    72,
    133,
    56,
    76,
    160,
    62,
    18,
    96,
    10,
    193,
    194,
    72,
    2,
    138,
    243,
    114,
    108,
    201,
    52,
    99,
    136,
    46,
    168,
    192,
    42,
    171
]);
const hashPlainTextVector = [
    {
        hash: "SHA-1",
        plainText: plainText.slice(0, 214)
    },
    {
        hash: "SHA-256",
        plainText: plainText.slice(0, 190)
    },
    {
        hash: "SHA-384",
        plainText: plainText.slice(0, 158)
    },
    {
        hash: "SHA-512",
        plainText: plainText.slice(0, 126)
    }
];
test(async function testEncryptDecrypt() {
    const subtle = window.crypto.subtle;
    assert(subtle);
    for (const { hash , plainText  } of hashPlainTextVector){
        const keyPair = await subtle.generateKey({
            name: "RSA-OAEP",
            modulusLength: 2048,
            publicExponent: new Uint8Array([
                1,
                0,
                1
            ]),
            hash
        }, true, [
            "encrypt",
            "decrypt"
        ]);
        const encryptAlgorithm = {
            name: "RSA-OAEP"
        };
        const cipherText = await subtle.encrypt(encryptAlgorithm, keyPair.publicKey, plainText);
        assert(cipherText);
        assert(cipherText.byteLength > 0);
        assertEquals(cipherText.byteLength * 8, 2048);
        assert(cipherText instanceof ArrayBuffer);
        const decrypted = await subtle.decrypt(encryptAlgorithm, keyPair.privateKey, cipherText);
        assert(decrypted);
        assert(decrypted instanceof ArrayBuffer);
        assertEquals(new Uint8Array(decrypted), plainText);
        const badPlainText = new Uint8Array(plainText.byteLength + 1);
        badPlainText.set(plainText, 0);
        badPlainText.set(new Uint8Array([
            32
        ]), plainText.byteLength);
        await assertRejects(async ()=>{
            await subtle.encrypt(encryptAlgorithm, keyPair.publicKey, badPlainText);
            throw new TypeError("unreachable");
        }, DOMException);
    }
});
test(async function testGenerateRSAKey() {
    const subtle = window.crypto.subtle;
    assert(subtle);
    const keyPair = await subtle.generateKey({
        name: "RSA-PSS",
        modulusLength: 2048,
        publicExponent: new Uint8Array([
            1,
            0,
            1
        ]),
        hash: "SHA-256"
    }, true, [
        "sign",
        "verify"
    ]);
    assert(keyPair.privateKey);
    assert(keyPair.publicKey);
    assertEquals(keyPair.privateKey.extractable, true);
    assert(keyPair.privateKey.usages.includes("sign"));
});
test(async function testGenerateHMACKey() {
    const key = await window.crypto.subtle.generateKey({
        name: "HMAC",
        hash: "SHA-512"
    }, true, [
        "sign",
        "verify"
    ]);
    assert(key);
    assertEquals(key.extractable, true);
    assert(key.usages.includes("sign"));
});
test(async function testECDSASignVerify() {
    const key = await window.crypto.subtle.generateKey({
        name: "ECDSA",
        namedCurve: "P-384"
    }, true, [
        "sign",
        "verify"
    ]);
    const encoder = new TextEncoder();
    const encoded = encoder.encode("Hello, World!");
    const signature = await window.crypto.subtle.sign({
        name: "ECDSA",
        hash: "SHA-384"
    }, key.privateKey, encoded);
    assert(signature);
    assert(signature instanceof ArrayBuffer);
    const verified = await window.crypto.subtle.verify({
        hash: {
            name: "SHA-384"
        },
        name: "ECDSA"
    }, key.publicKey, signature, encoded);
    assert(verified);
});
test(async function testECDSASignVerifyFail() {
    const key = await window.crypto.subtle.generateKey({
        name: "ECDSA",
        namedCurve: "P-384"
    }, true, [
        "sign",
        "verify"
    ]);
    const encoded = new Uint8Array([
        1
    ]);
    await assertRejects(async ()=>{
        await window.crypto.subtle.sign({
            name: "ECDSA",
            hash: "SHA-384"
        }, key.publicKey, new Uint8Array([
            1
        ]));
        throw new TypeError("unreachable");
    }, DOMException);
    const signature = await window.crypto.subtle.sign({
        name: "ECDSA",
        hash: "SHA-384"
    }, key.privateKey, encoded);
    await assertRejects(async ()=>{
        await window.crypto.subtle.verify({
            hash: {
                name: "SHA-384"
            },
            name: "ECDSA"
        }, key.privateKey, signature, encoded);
        throw new TypeError("unreachable");
    }, DOMException);
});
test(async function testSignRSASSAKey() {
    const subtle = window.crypto.subtle;
    assert(subtle);
    const keyPair = await subtle.generateKey({
        name: "RSASSA-PKCS1-v1_5",
        modulusLength: 2048,
        publicExponent: new Uint8Array([
            1,
            0,
            1
        ]),
        hash: "SHA-256"
    }, true, [
        "sign",
        "verify"
    ]);
    assert(keyPair.privateKey);
    assert(keyPair.publicKey);
    assertEquals(keyPair.privateKey.extractable, true);
    assert(keyPair.privateKey.usages.includes("sign"));
    const encoder = new TextEncoder();
    const encoded = encoder.encode("Hello, World!");
    const signature = await window.crypto.subtle.sign({
        name: "RSASSA-PKCS1-v1_5"
    }, keyPair.privateKey, encoded);
    assert(signature);
});
const rawKey = new Uint8Array([
    1,
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15,
    16
]);
const jwk: JsonWebKey = {
    kty: "oct",
    k: "AQIDBAUGBwgJCgsMDQ4PEA",
    alg: "HS256",
    ext: true,
    "key_ops": [
        "sign"
    ]
};
test(async function subtleCryptoHmacImportExport() {
    const key1 = await crypto.subtle.importKey("raw", rawKey, {
        name: "HMAC",
        hash: "SHA-256"
    }, true, [
        "sign"
    ]);
    const key2 = await crypto.subtle.importKey("jwk", jwk, {
        name: "HMAC",
        hash: "SHA-256"
    }, true, [
        "sign"
    ]);
    const actual1 = await crypto.subtle.sign({
        name: "HMAC"
    }, key1, new Uint8Array([
        1,
        2,
        3,
        4
    ]));
    const actual2 = await crypto.subtle.sign({
        name: "HMAC"
    }, key2, new Uint8Array([
        1,
        2,
        3,
        4
    ]));
    const expected = new Uint8Array([
        59,
        170,
        255,
        216,
        51,
        141,
        51,
        194,
        213,
        48,
        41,
        191,
        184,
        40,
        216,
        47,
        130,
        165,
        203,
        26,
        163,
        43,
        38,
        71,
        23,
        122,
        222,
        1,
        146,
        46,
        182,
        87
    ]);
    assertEquals(new Uint8Array(actual1), expected);
    assertEquals(new Uint8Array(actual2), expected);
    const exportedKey1 = await crypto.subtle.exportKey("raw", key1);
    assertEquals(new Uint8Array(exportedKey1), rawKey);
    const exportedKey2 = await crypto.subtle.exportKey("jwk", key2);
    assertEquals(exportedKey2, jwk);
});
test(async function generateImportHmacJwk() {
    const key = await crypto.subtle.generateKey({
        name: "HMAC",
        hash: "SHA-512"
    }, true, [
        "sign"
    ]);
    assert(key);
    assertEquals(key.type, "secret");
    assertEquals(key.extractable, true);
    assertEquals(key.usages, [
        "sign"
    ]);
    const exportedKey = await crypto.subtle.exportKey("jwk", key);
    assertEquals(exportedKey.kty, "oct");
    assertEquals(exportedKey.alg, "HS512");
    assertEquals(exportedKey.key_ops, [
        "sign"
    ]);
    assertEquals(exportedKey.ext, true);
    assert(typeof exportedKey.k == "string");
    assertEquals(exportedKey.k.length, 171);
});
const pkcs8TestVectors = [
    {
        pem: "id_rsaEncryption.pem",
        hash: "SHA-256"
    }
];
test({
    permissions: {
        read: true
    }
}, async function importRsaPkcs8() {
    const pemHeader = "-----BEGIN PRIVATE KEY-----";
    const pemFooter = "-----END PRIVATE KEY-----";
    for (const { pem , hash  } of pkcs8TestVectors){
        const keyFile = await Deno.readTextFile(pem);
        const pemContents = keyFile.substring(pemHeader.length, keyFile.length - pemFooter.length);
        const binaryDerString = atob(pemContents);
        const binaryDer = new Uint8Array(binaryDerString.length);
        for(let i = 0; i < binaryDerString.length; i++){
            binaryDer[i] = binaryDerString.charCodeAt(i);
        }
        const key = await crypto.subtle.importKey("pkcs8", binaryDer, {
            name: "RSA-PSS",
            hash
        }, true, [
            "sign"
        ]);
        assert(key);
        assertEquals(key.type, "private");
        assertEquals(key.extractable, true);
        assertEquals(key.usages, [
            "sign"
        ]);
        const algorithm = key.algorithm as RsaHashedKeyAlgorithm;
        assertEquals(algorithm.name, "RSA-PSS");
        assertEquals(algorithm.hash.name, hash);
        assertEquals(algorithm.modulusLength, 2048);
        assertEquals(algorithm.publicExponent, new Uint8Array([
            1,
            0,
            1
        ]));
    }
});
const nonInteroperableVectors = [
    {
        pem: "id_rsassaPss.pem",
        hash: "SHA-256"
    },
    {
        pem: "id_rsassaPss_default.pem",
        hash: "SHA-1"
    },
    {
        pem: "id_rsassaPss_saltLen_30.pem",
        hash: "SHA-1"
    }
];
test({
    permissions: {
        read: true
    }
}, async function importNonInteroperableRsaPkcs8() {
    const pemHeader = "-----BEGIN PRIVATE KEY-----";
    const pemFooter = "-----END PRIVATE KEY-----";
    for (const { pem , hash  } of nonInteroperableVectors){
        const keyFile = await Deno.readTextFile(pem);
        const pemContents = keyFile.substring(pemHeader.length, keyFile.length - pemFooter.length);
        const binaryDerString = atob(pemContents);
        const binaryDer = new Uint8Array(binaryDerString.length);
        for(let i = 0; i < binaryDerString.length; i++){
            binaryDer[i] = binaryDerString.charCodeAt(i);
        }
        await assertRejects(()=>crypto.subtle.importKey("pkcs8", binaryDer, {
                name: "RSA-PSS",
                hash
            }, true, [
                "sign"
            ]), DOMException, "unsupported algorithm");
    }
});
const asn1AlgorithmIdentifier = new Uint8Array([
    0x02,
    0x01,
    0x00,
    0x30,
    0x0d,
    0x06,
    0x09,
    0x2a,
    0x86,
    0x48,
    0x86,
    0xf7,
    0x0d,
    0x01,
    0x01,
    0x01,
    0x05,
    0x00
]);
test(async function rsaExport() {
    for (const algorithm of [
        "RSASSA-PKCS1-v1_5",
        "RSA-PSS",
        "RSA-OAEP"
    ]){
        const keyPair = await crypto.subtle.generateKey({
            name: algorithm,
            modulusLength: 2048,
            publicExponent: new Uint8Array([
                1,
                0,
                1
            ]),
            hash: "SHA-256"
        }, true, algorithm !== "RSA-OAEP" ? [
            "sign",
            "verify"
        ] : [
            "encrypt",
            "decrypt"
        ]);
        assert(keyPair.privateKey);
        assert(keyPair.publicKey);
        assertEquals(keyPair.privateKey.extractable, true);
        const exportedPrivateKey = await crypto.subtle.exportKey("pkcs8", keyPair.privateKey);
        assert(exportedPrivateKey);
        assert(exportedPrivateKey instanceof ArrayBuffer);
        const pkcs8 = new Uint8Array(exportedPrivateKey);
        assert(pkcs8.length > 0);
        assertEquals(pkcs8.slice(4, asn1AlgorithmIdentifier.byteLength + 4), asn1AlgorithmIdentifier);
        const exportedPublicKey = await crypto.subtle.exportKey("spki", keyPair.publicKey);
        const spki = new Uint8Array(exportedPublicKey);
        assert(spki.length > 0);
        assertEquals(spki.slice(4, asn1AlgorithmIdentifier.byteLength + 1), asn1AlgorithmIdentifier.slice(3));
    }
});
test(async function testHkdfDeriveBits() {
    const rawKey = crypto.getRandomValues(new Uint8Array(16));
    const key = await crypto.subtle.importKey("raw", rawKey, {
        name: "HKDF",
        hash: "SHA-256"
    }, false, [
        "deriveBits"
    ]);
    const salt = crypto.getRandomValues(new Uint8Array(16));
    const info = crypto.getRandomValues(new Uint8Array(16));
    const result = await crypto.subtle.deriveBits({
        name: "HKDF",
        hash: "SHA-256",
        salt: salt,
        info: info
    }, key, 128);
    assertEquals(result.byteLength, 128 / 8);
});
test(async function testHkdfDeriveBitsWithLargeKeySize() {
    const key = await crypto.subtle.importKey("raw", new Uint8Array([
        0x00
    ]), "HKDF", false, [
        "deriveBits"
    ]);
    await assertRejects(()=>crypto.subtle.deriveBits({
            name: "HKDF",
            hash: "SHA-1",
            salt: new Uint8Array(),
            info: new Uint8Array()
        }, key, ((20 * 255) << 3) + 8), DOMException, "The length provided for HKDF is too large");
});
test(async function testEcdhDeriveBitsWithShorterLength() {
    const keypair = await crypto.subtle.generateKey({
        name: "ECDH",
        namedCurve: "P-384"
    }, true, [
        "deriveBits",
        "deriveKey"
    ]);
    const result = await crypto.subtle.deriveBits({
        name: "ECDH",
        public: keypair.publicKey
    }, keypair.privateKey, 256);
    assertEquals(result.byteLength * 8, 256);
});
test(async function testEcdhDeriveBitsWithLongerLength() {
    const keypair = await crypto.subtle.generateKey({
        name: "ECDH",
        namedCurve: "P-384"
    }, true, [
        "deriveBits",
        "deriveKey"
    ]);
    await assertRejects(()=>crypto.subtle.deriveBits({
            name: "ECDH",
            public: keypair.publicKey
        }, keypair.privateKey, 512), DOMException, "Invalid length");
});
test(async function testEcdhDeriveBitsWithNullLength() {
    const keypair = await crypto.subtle.generateKey({
        name: "ECDH",
        namedCurve: "P-384"
    }, true, [
        "deriveBits",
        "deriveKey"
    ]);
    const result = await crypto.subtle.deriveBits({
        name: "ECDH",
        public: keypair.publicKey
    }, keypair.privateKey, null);
    assertEquals(result.byteLength * 8, 384);
});
test(async function testDeriveKey() {
    const rawKey = crypto.getRandomValues(new Uint8Array(16));
    const key = await crypto.subtle.importKey("raw", rawKey, "PBKDF2", false, [
        "deriveKey",
        "deriveBits"
    ]);
    const salt = crypto.getRandomValues(new Uint8Array(16));
    const derivedKey = await crypto.subtle.deriveKey({
        name: "PBKDF2",
        salt,
        iterations: 1000,
        hash: "SHA-256"
    }, key, {
        name: "HMAC",
        hash: "SHA-256"
    }, true, [
        "sign"
    ]);
    assert(derivedKey instanceof CryptoKey);
    assertEquals(derivedKey.type, "secret");
    assertEquals(derivedKey.extractable, true);
    assertEquals(derivedKey.usages, [
        "sign"
    ]);
    const algorithm = derivedKey.algorithm as HmacKeyAlgorithm;
    assertEquals(algorithm.name, "HMAC");
    assertEquals(algorithm.hash.name, "SHA-256");
    assertEquals(algorithm.length, 512);
});
test(async function testAesCbcEncryptDecrypt() {
    const key = await crypto.subtle.generateKey({
        name: "AES-CBC",
        length: 128
    }, true, [
        "encrypt",
        "decrypt"
    ]);
    const iv = crypto.getRandomValues(new Uint8Array(16));
    const encrypted = await crypto.subtle.encrypt({
        name: "AES-CBC",
        iv
    }, key as CryptoKey, new Uint8Array([
        1,
        2,
        3,
        4,
        5,
        6
    ]));
    assert(encrypted instanceof ArrayBuffer);
    assertEquals(encrypted.byteLength, 16);
    const decrypted = await crypto.subtle.decrypt({
        name: "AES-CBC",
        iv
    }, key as CryptoKey, encrypted);
    assert(decrypted instanceof ArrayBuffer);
    assertEquals(decrypted.byteLength, 6);
    assertEquals(new Uint8Array(decrypted), new Uint8Array([
        1,
        2,
        3,
        4,
        5,
        6
    ]));
});
test(async function testAesCtrEncryptDecrypt() {
    async function aesCtrRoundTrip(key: CryptoKey, counter: Uint8Array, length: number, plainText: Uint8Array) {
        const cipherText = await crypto.subtle.encrypt({
            name: "AES-CTR",
            counter,
            length
        }, key, plainText);
        assert(cipherText instanceof ArrayBuffer);
        assertEquals(cipherText.byteLength, plainText.byteLength);
        assertNotEquals(new Uint8Array(cipherText), plainText);
        const decryptedText = await crypto.subtle.decrypt({
            name: "AES-CTR",
            counter,
            length
        }, key, cipherText);
        assert(decryptedText instanceof ArrayBuffer);
        assertEquals(decryptedText.byteLength, plainText.byteLength);
        assertEquals(new Uint8Array(decryptedText), plainText);
    }
    for (const keySize of [
        128,
        192,
        256
    ]){
        const key = await crypto.subtle.generateKey({
            name: "AES-CTR",
            length: keySize
        }, true, [
            "encrypt",
            "decrypt"
        ]) as CryptoKey;
        for (const length of [
            128
        ]){
            const counter = crypto.getRandomValues(new Uint8Array(16));
            await aesCtrRoundTrip(key, counter, length, new Uint8Array([
                1,
                2,
                3,
                4,
                5,
                6
            ]));
        }
        for (const length of [
            32,
            64,
            128
        ]){
            const plaintext1 = crypto.getRandomValues(new Uint8Array(32));
            const counter = new Uint8Array(16);
            for(let off = 0; off < 16 - (length / 8); ++off){
                counter[off] = off;
            }
            const ciphertext1 = await crypto.subtle.encrypt({
                name: "AES-CTR",
                counter,
                length
            }, key, plaintext1);
            for(let off = 16 - (length / 8); off < 16; ++off){
                counter[off] = 0xff;
            }
            const plaintext2 = new Uint8Array(48);
            plaintext2.set(plaintext1, 16);
            const ciphertext2 = await crypto.subtle.encrypt({
                name: "AES-CTR",
                counter,
                length
            }, key, plaintext2);
            assertEquals(new Uint8Array(ciphertext1), new Uint8Array(ciphertext2).slice(16));
        }
    }
});
test(async function testECDH() {
    for (const keySize of [
        256,
        384
    ]){
        const keyPair = await crypto.subtle.generateKey({
            name: "ECDH",
            namedCurve: "P-" + keySize
        }, true, [
            "deriveBits"
        ]);
        const derivedKey = await crypto.subtle.deriveBits({
            name: "ECDH",
            public: keyPair.publicKey
        }, keyPair.privateKey, keySize);
        assert(derivedKey instanceof ArrayBuffer);
        assertEquals(derivedKey.byteLength, keySize / 8);
    }
});
test(async function testWrapKey() {
    const key = await crypto.subtle.generateKey({
        name: "RSA-OAEP",
        modulusLength: 4096,
        publicExponent: new Uint8Array([
            1,
            0,
            1
        ]),
        hash: "SHA-256"
    }, true, [
        "wrapKey",
        "unwrapKey"
    ]);
    const hmacKey = await crypto.subtle.generateKey({
        name: "HMAC",
        hash: "SHA-256",
        length: 128
    }, true, [
        "sign"
    ]);
    const wrappedKey = await crypto.subtle.wrapKey("raw", hmacKey, key.publicKey, {
        name: "RSA-OAEP",
        label: new Uint8Array(8)
    });
    assert(wrappedKey instanceof ArrayBuffer);
    assertEquals(wrappedKey.byteLength, 512);
});
test.ignore(async function testAesKeyGen() {
    const key = await crypto.subtle.generateKey({
        name: "AES-GCM",
        length: 256
    }, true, [
        "encrypt",
        "decrypt"
    ]);
    assert(key);
    assertEquals(key.type, "secret");
    assertEquals(key.extractable, true);
    assertEquals(key.usages, [
        "encrypt",
        "decrypt"
    ]);
    const algorithm = key.algorithm as AesKeyAlgorithm;
    assertEquals(algorithm.name, "AES-GCM");
    assertEquals(algorithm.length, 256);
});
test.ignore(async function testUnwrapKey() {
    const subtle = crypto.subtle;
    const AES_KEY: AesKeyAlgorithm & AesCbcParams = {
        name: "AES-CBC",
        length: 128,
        iv: new Uint8Array(16)
    };
    const RSA_KEY: RsaHashedKeyGenParams & RsaOaepParams = {
        name: "RSA-OAEP",
        modulusLength: 2048,
        publicExponent: new Uint8Array([
            1,
            0,
            1
        ]),
        hash: "SHA-1"
    };
    const aesKey = await subtle.generateKey(AES_KEY, true, [
        "encrypt",
        "decrypt"
    ]);
    const rsaKeyPair = await subtle.generateKey({
        name: "RSA-OAEP",
        hash: "SHA-1",
        publicExponent: new Uint8Array([
            1,
            0,
            1
        ]),
        modulusLength: 2048
    }, false, [
        "wrapKey",
        "encrypt",
        "unwrapKey",
        "decrypt"
    ]);
    const enc = await subtle.wrapKey("raw", aesKey, rsaKeyPair.publicKey, RSA_KEY);
    const unwrappedKey = await subtle.unwrapKey("raw", enc, rsaKeyPair.privateKey, RSA_KEY, AES_KEY, false, [
        "encrypt",
        "decrypt"
    ]);
    assert(unwrappedKey instanceof CryptoKey);
    assertEquals(unwrappedKey.type, "secret");
    assertEquals(unwrappedKey.extractable, false);
    assertEquals(unwrappedKey.usages, [
        "encrypt",
        "decrypt"
    ]);
});
test(async function testDecryptWithInvalidIntializationVector() {
    const data = new Uint8Array([
        42,
        42,
        42,
        42,
        42,
        42,
        42,
        42,
        42,
        42,
        42,
        42,
        42,
        42,
        42
    ]);
    const key = await crypto.subtle.importKey("raw", new Uint8Array(16), {
        name: "AES-CBC",
        length: 256
    }, true, [
        "encrypt",
        "decrypt"
    ]);
    const initVector = new Uint8Array([
        0,
        1,
        2,
        3,
        4,
        5,
        6,
        7,
        8,
        9,
        10,
        11,
        12,
        13,
        14,
        15
    ]);
    const encrypted = await crypto.subtle.encrypt({
        name: "AES-CBC",
        iv: initVector
    }, key, data);
    const initVector2 = new Uint8Array([
        15,
        14,
        13,
        12,
        11,
        10,
        9,
        8,
        7,
        6,
        5,
        4,
        3,
        2,
        1,
        0
    ]);
    await assertRejects(async ()=>{
        await crypto.subtle.decrypt({
            name: "AES-CBC",
            iv: initVector2
        }, key, encrypted);
    }, DOMException);
});
const jwtRSAKeys = {
    "1024": {
        size: 1024,
        publicJWK: {
            kty: "RSA",
            n: "zZn4sRGfjQos56yL_Qy1R9NI-THMnFynn94g5RxA6wGrJh4BJT3x6I9x0IbpS3q-d4ORA6R2vuDMh8dDFRr9RDH6XY-gUScc9U5Jz3UA2KmVfsCbnUPvcAmMV_ENA7_TF0ivVjuIFodyDTx7EKHNVTrHHSlrbt7spbmcivs23Zc",
            e: "AQAB"
        },
        privateJWK: {
            kty: "RSA",
            n: "zZn4sRGfjQos56yL_Qy1R9NI-THMnFynn94g5RxA6wGrJh4BJT3x6I9x0IbpS3q-d4ORA6R2vuDMh8dDFRr9RDH6XY-gUScc9U5Jz3UA2KmVfsCbnUPvcAmMV_ENA7_TF0ivVjuIFodyDTx7EKHNVTrHHSlrbt7spbmcivs23Zc",
            e: "AQAB",
            d: "YqIK_GdH85F-GWZdgfgmv15NE78gOaL5h2g4v7DeM9-JC7A5PHSLKNYn87HFGcC4vv0PBIBRtyCA_mJJfEaGWORVCOXSBpWNepMYpio52n3w5uj5UZEsBnbtZc0EtWhVF2Auqa7VbiKrWcQUEgEI8V0gE5D4tyBg8GXv9975dQE",
            p: "9BrAg5L1zfqGPuWJDuDCBX-TmtZdrOI3Ys4ZaN-yMPlTjwWSEPO0qnfjEZcw2VgXHgJJmbVco6TxckJCmEYqeQ",
            q: "157jDJ1Ya5nmQvTPbhKAPAeMWogxCyaQTkBrp30pEKd6mGSB385hqr4BIk8s3f7MdXpM-USpaZgUoT4o_2VEjw",
            dp: "qdd_QUzcaB-6jkKo1Ug-1xKIAgDLFsIjJUUfWt_iHL8ti2Kl2dOnTcCypgebPm5TT1bqHN-agGYAdK5zpX2UiQ",
            dq: "hNRfwOSplNfhLvxLUN7a2qA3yYm-1MSz_1DWQP7srlLORlUcYPht2FZmsnEeDcAqynBGPQUcbG2Av_hgHz2OZw",
            qi: "zbpJQAhinrxSbVKxBQ2EZGFUD2e3WCXbAJRYpk8HVQ5AA52OhKTicOye2hEHnrgpFKzC8iznTsCG3FMkvwcj4Q"
        }
    },
    "2048": {
        size: 2048,
        publicJWK: {
            kty: "RSA",
            n: "09eVwAhT9SPBxdEN-74BBeEANGaVGwqH-YglIc4VV7jfhR2by5ivzVq8NCeQ1_ACDIlTDY8CTMQ5E1c1SEXmo_T7q84XUGXf8U9mx6uRg46sV7fF-hkwJR80BFVsvWxp4ahPlVJYj__94ft7rIVvchb5tyalOjrYFCJoFnSgq-i3ZjU06csI9XnO5klINucD_Qq0vUhO23_Add2HSYoRjab8YiJJR_Eths7Pq6HHd2RSXmwYp5foRnwe0_U75XmesHWDJlJUHYbwCZo0kP9G8g4QbucwU-MSNBkZOO2x2ZtZNexpHd0ThkATbnNlpVG_z2AGNORp_Ve3rlXwrGIXXw",
            e: "AQAB"
        },
        privateJWK: {
            kty: "RSA",
            n: "09eVwAhT9SPBxdEN-74BBeEANGaVGwqH-YglIc4VV7jfhR2by5ivzVq8NCeQ1_ACDIlTDY8CTMQ5E1c1SEXmo_T7q84XUGXf8U9mx6uRg46sV7fF-hkwJR80BFVsvWxp4ahPlVJYj__94ft7rIVvchb5tyalOjrYFCJoFnSgq-i3ZjU06csI9XnO5klINucD_Qq0vUhO23_Add2HSYoRjab8YiJJR_Eths7Pq6HHd2RSXmwYp5foRnwe0_U75XmesHWDJlJUHYbwCZo0kP9G8g4QbucwU-MSNBkZOO2x2ZtZNexpHd0ThkATbnNlpVG_z2AGNORp_Ve3rlXwrGIXXw",
            e: "AQAB",
            d: "H4xboN2co0VP9kXL71G8lUOM5EDis8Q9u8uqu_4U75t4rjpamVeD1vFMVfgOehokM_m_hKVnkkcmuNqj9L90ObaiRFPM5QxG7YkFpXbHlPAKeoXD1hsqMF0VQg_2wb8DhberInHA_rEA_kaVhHvavQLu7Xez45gf1d_J4I4931vjlCB6cupbLL0H5hHsxbMsX_5nnmAJdL_U3gD-U7ZdQheUPhDBJR2KeGzvnTm3KVKpOnwn-1Cd45MU4-KDdP0FcBVEuBsSrsQHliTaciBgkbyj__BangPj3edDxTkb-fKkEvhkXRjAoJs1ixt8nfSGDce9cM_GqAX9XGb4s2QkAQ",
            dp: "mM82RBwzGzi9LAqjGbi-badLtHRRBoH9sfMrJuOtzxRnmwBFccg_lwy-qAhUTqnN9kvD0H1FzXWzoFPFJbyi-AOmumYGpWm_PvzQGldne5CPJ02pYaeg-t1BePsT3OpIq0Am8E2Kjf9polpRJwIjO7Kx8UJKkhg5bISnsy0V8wE",
            dq: "ZlM4AvrWIpXwqsH_5Q-6BsLJdbnN_GypFCXoT9VXniXncSBZIWCkgDndBdWkSzyzIN65NiMRBfZaf9yduTFj4kvOPwb3ch3J0OxGJk0Ary4OGSlS1zNwMl93ALGal1FzpWUuiia9L9RraGqXAUr13L7TIIMRobRjpAV-z7M-ruM",
            p: "7VwGt_tJcAFQHrmDw5dM1EBru6fidM45NDv6VVOEbxKuD5Sh2EfAHfm5c6oouA1gZqwvKH0sn_XpB1NsyYyHEQd3sBVdK0zRjTo-E9mRP-1s-LMd5YDXVq6HE339nxpXsmO25slQEF6zBrj1bSNNXBFc7fgDnlq-HIeleMvsY_E",
            q: "5HqMHLzb4IgXhUl4pLz7E4kjY8PH2YGzaQfK805zJMbOXzmlZK0hizKo34Qqd2nB9xos7QgzOYQrNfSWheARwVsSQzAE0vGvw3zHIPP_lTtChBlCTPctQcURjw4dXcnK1oQ-IT321FNOW3EO-YTsyGcypJqJujlZrLbxYjOjQE8",
            qi: "OQXzi9gypDnpdHatIi0FaUGP8LSzfVH0AUugURJXs4BTJpvA9y4hcpBQLrcl7H_vq6kbGmvC49V-9I5HNVX_AuxGIXKuLZr5WOxPq8gLTqHV7X5ZJDtWIP_nq2NNgCQQyNNRrxebiWlwGK9GnX_unewT6jopI_oFhwp0Q13rBR0"
        }
    },
    "4096": {
        size: 4096,
        publicJWK: {
            kty: "RSA",
            n: "2qr2TL2c2JmbsN0OLIRnaAB_ZKb1-Gh9H0qb4lrBuDaqkW_eFPwT-JIsvnNJvDT7BLJ57tTMIj56ZMtv6efSSTWSk9MOoW2J1K_iEretZ2cegB_aRX7qQVjnoFsz9U02BKfAIUT0o_K7b9G08d1rrAUohi_SVQhwObodg7BddMbKUmz70QNIS487LN44WUVnn9OgE9atTYUARNukT0DuQb3J-K20ksTuVujXbSelohDmLobqlGoi5sY_548Qs9BtFmQ2nGuEHNB2zdlZ5EvEqbUFVZ2QboG6jXdoos6qcwdgUvAhj1Hz10Ngic_RFqL7bNDoIOzNp66hdA35uxbwuaygZ16ikxoPj7eTYud1hrkyQCgeGw2YhCiKIE6eos_U5dL7WHRD5aSkkzsgXtnF8pVmStsuf0QcdAoC-eeCex0tSTgRw9AtGTz8Yr1tGQD9l_580zAXnE6jmrwRRQ68EEA7vohGov3tnG8pGyg_zcxeADLtPlfTc1tEwmh3SGrioDClioYCipm1JvkweEgP9eMPpEC8SgRU1VNDSVe1SF4uNsH8vA7PHFKfg6juqJEc5ht-l10FYER-Qq6bZXsU2oNcfE5SLDeLTWmxiHmxK00M8ABMFIV5gUkPoMiWcl87O6XwzA2chsIERp7Vb-Vn2O-EELiXzv7lPhc6fTGQ0Nc",
            e: "AQAB"
        },
        privateJWK: {
            kty: "RSA",
            n: "2qr2TL2c2JmbsN0OLIRnaAB_ZKb1-Gh9H0qb4lrBuDaqkW_eFPwT-JIsvnNJvDT7BLJ57tTMIj56ZMtv6efSSTWSk9MOoW2J1K_iEretZ2cegB_aRX7qQVjnoFsz9U02BKfAIUT0o_K7b9G08d1rrAUohi_SVQhwObodg7BddMbKUmz70QNIS487LN44WUVnn9OgE9atTYUARNukT0DuQb3J-K20ksTuVujXbSelohDmLobqlGoi5sY_548Qs9BtFmQ2nGuEHNB2zdlZ5EvEqbUFVZ2QboG6jXdoos6qcwdgUvAhj1Hz10Ngic_RFqL7bNDoIOzNp66hdA35uxbwuaygZ16ikxoPj7eTYud1hrkyQCgeGw2YhCiKIE6eos_U5dL7WHRD5aSkkzsgXtnF8pVmStsuf0QcdAoC-eeCex0tSTgRw9AtGTz8Yr1tGQD9l_580zAXnE6jmrwRRQ68EEA7vohGov3tnG8pGyg_zcxeADLtPlfTc1tEwmh3SGrioDClioYCipm1JvkweEgP9eMPpEC8SgRU1VNDSVe1SF4uNsH8vA7PHFKfg6juqJEc5ht-l10FYER-Qq6bZXsU2oNcfE5SLDeLTWmxiHmxK00M8ABMFIV5gUkPoMiWcl87O6XwzA2chsIERp7Vb-Vn2O-EELiXzv7lPhc6fTGQ0Nc",
            e: "AQAB",
            d: "uXPRXBhcE5-DWabBRKQuhxgU8ype5gTISWefeYP7U96ZHqu_sBByZ5ihdgyU9pgAZGVx4Ep9rnVKnH2lNr2zrP9Qhyqy99nM0aMxmypIWLAuP__DwLj4t99M4sU29c48CAq1egHfccSFjzpNuetOTCA71EJuokt70pm0OmGzgTyvjuR7VTLxd5PMXitBowSn8_cphmnFpT8tkTiuy8CH0R3DU7MOuINomDD1s8-yPBcVAVTPUnwJiauNuzestLQKMLlhT5wn-cAbYk36XRKdgkjSc2AkhHRl4WDqT1nzWYdh_DVIYSLiKSktkPO9ovMrRYiPtozfhl0m9SR9Ll0wXtcnnDlWXc_MSGpw18vmUBSJ4PIhkiFsvLn-db3wUkA8uve-iqqfk0sxlGWughWx03kGmZDmprWbXugCBHfsI4X93w4exznXH_tapxPnmjbhVUQR6p41MvO2lcHWPLwGJgLIoejBHpnn3TmMN0UjFZki7q9B_dJ3fXh0mX9DzAlC0sil1NgCPhMPq02393_giinQquMknrBvgKxGSfGUrDKuflCx611ZZlRM3R7YMX2OIy1g4DyhPzBVjxRMtm8PnIs3m3Hi-O-C_PHF93w9J8Wqd0yIw7SpavDqZXLPC6Cqi8K7MBZyVECXHtRj1bBqT-h_xZmFCDjSU0NqfOdgApE",
            p: "9NrXwq4kY9kBBOwLoFZVQc4kJI_NbKa_W9FLdQdRIbMsZZHXJ3XDUR9vJAcaaR75WwIC7X6N55nVtWTq28Bys9flJ9RrCTfciOntHEphBhYaL5ZTUl-6khYmsOf_psff2VaOOCvHGff5ejuOmBQxkw2E-cv7knRgWFHoLWpku2NJIMuGHt9ks7OAUfIZVYl9YJnw4FYUzhgaxemknjLeZ8XTkGW2zckzF-d95YI9i8zD80Umubsw-YxriSfqFQ0rGHBsbQ8ZOTd_KJju42BWnXIjNDYmjFUqdzVjI4XQ8EGrCEf_8_iwphGyXD7LOJ4fqd97B3bYpoRTPnCgY_SEHQ",
            q: "5J758_NeKr1XPZiLxXohYQQnh0Lb4QtGZ1xzCgjhBQLcIBeTOG_tYjCues9tmLt93LpJfypSJ-SjDLwkR2s069_IByYGpxyeGtV-ulqYhSw1nD2CXKMDGyO5jXDs9tJrS_UhfobXKQH03CRdFugyPkSNmXY-AafFynG7xLr7oYBC05FnhUXPm3VBTPt9K-BpqwYd_h9vkAWeprSPo83UlwcLMupSJY9LaHxhRdz2yi0ZKNwXXHRwcszGjDBvvzUcCYbqWqjzbEvFY6KtH8Jh4LhM46rHaoEOTernJsDF6a6W8Df88RthqTExcwnaQf0O_dlbjSxEIPfbxx8t1EQugw",
            dp: "4Y7Hu5tYAnLhMXuQqj9dgqU3PkcKYdCp7xc6f7Ah2P2JJHfYz4z4RD7Ez1eLyNKzulZ8A_PVHUjlSZiRkaYTBAEaJDrV70P6cFWuC6WpA0ZREQ1V7EgrQnANbGILa8QsPbYyhSQu4YlB1IwQq5_OmzyVBtgWA7AZIMMzMsMT0FuB_if-gWohBjmRN-vh0p45VUf6UW568-_YmgDFmMYbg1UFs7s_TwrNenPR0h7MO4CB8hP9vJLoZrooRczzIjljPbwy5bRG9CJfjTJ0vhj9MUT3kR1hHV1HJVGU5iBbfTfBKnvJGSI6-IDM4ZUm-B0R5hbs6s9cfOjhFmACIJIbMQ",
            dq: "gT4iPbfyHyVEwWyQb4X4grjvg7bXSKSwG1SXMDAOzV9tg7LwJjKYNy8gJAtJgNNVdsfVLs-E_Epzpoph1AIWO9YZZXkov6Yc9zyEVONMX9S7ReU74hTBd8E9b2lMfMg9ogYk9jtSPTt-6kigW4fOh4cHqZ6_tP3cgfLD3JZ8FDPHE4WaySvLDq49yUBO5dQKyIU_xV6OGhQjOUjP_yEoMmzn9tOittsIHTxbXTxqQ6c1FvU9O6YTv8Jl5_Cl66khfX1I1RG38xvurcHULyUbYgeuZ_Iuo9XreT73h9_owo9RguGT29XH4vcNZmRGf5GIvRb4e5lvtleIZkwJA3u78w",
            qi: "JHmVKb1zwW5iRR6RCeexYnh2fmY-3DrPSdM8Dxhr0F8dayi-tlRqEdnG0hvp45n8gLUskWWcB9EXlUJObZGKDfGuxgMa3g_xeLA2vmFQ12MxPsyH4iCNZvsgmGxx7TuOHrnDh5EBVnM4_de63crEJON2sYI8Ozi-xp2OEmAr2seWKq4sxkFni6exLhqb-NE4m9HMKlng1EtQh2rLBFG1VYD3SYYpMLc5fxzqGvSxn3Fa-Xgg-IZPY3ubrcm52KYgmLUGmnYStfVqGSWSdhDXHlNgI5pdAA0FzpyBk3ZX-JsxhwcnneKrYBBweq06kRMGWgvdbdAQ-7wSeGqqj5VPwA"
        }
    }
};
test(async function testImportRsaJwk() {
    const subtle = window.crypto.subtle;
    assert(subtle);
    for (const [_key, jwkData] of Object.entries(jwtRSAKeys)){
        const { size , publicJWK , privateJWK  } = jwkData;
        if (size < 2048) {
            continue;
        }
        for (const hash of [
            "SHA-1",
            "SHA-256",
            "SHA-384",
            "SHA-512"
        ]){
            const hashMapPSS: Record<string, string> = {
                "SHA-1": "PS1",
                "SHA-256": "PS256",
                "SHA-384": "PS384",
                "SHA-512": "PS512"
            };
            if (size == 1024 && hash == "SHA-512") {
                continue;
            }
            const privateKeyPSS = await crypto.subtle.importKey("jwk", {
                alg: hashMapPSS[hash],
                ...privateJWK,
                ext: true,
                "key_ops": [
                    "sign"
                ]
            }, {
                name: "RSA-PSS",
                hash
            }, true, [
                "sign"
            ]);
            const publicKeyPSS = await crypto.subtle.importKey("jwk", {
                alg: hashMapPSS[hash],
                ...publicJWK,
                ext: true,
                "key_ops": [
                    "verify"
                ]
            }, {
                name: "RSA-PSS",
                hash
            }, true, [
                "verify"
            ]);
            const signaturePSS = await crypto.subtle.sign({
                name: "RSA-PSS",
                saltLength: 32
            }, privateKeyPSS, new Uint8Array([
                1,
                2,
                3,
                4
            ]));
            const verifyPSS = await crypto.subtle.verify({
                name: "RSA-PSS",
                saltLength: 32
            }, publicKeyPSS, signaturePSS, new Uint8Array([
                1,
                2,
                3,
                4
            ]));
            assert(verifyPSS);
        }
        for (const hash of [
            "SHA-1",
            "SHA-256",
            "SHA-384",
            "SHA-512"
        ]){
            const hashMapPKCS1: Record<string, string> = {
                "SHA-1": "RS1",
                "SHA-256": "RS256",
                "SHA-384": "RS384",
                "SHA-512": "RS512"
            };
            if (size == 1024 && hash == "SHA-512") {
                continue;
            }
            const privateKeyPKCS1 = await crypto.subtle.importKey("jwk", {
                alg: hashMapPKCS1[hash],
                ...privateJWK,
                ext: true,
                "key_ops": [
                    "sign"
                ]
            }, {
                name: "RSASSA-PKCS1-v1_5",
                hash
            }, true, [
                "sign"
            ]);
            const publicKeyPKCS1 = await crypto.subtle.importKey("jwk", {
                alg: hashMapPKCS1[hash],
                ...publicJWK,
                ext: true,
                "key_ops": [
                    "verify"
                ]
            }, {
                name: "RSASSA-PKCS1-v1_5",
                hash
            }, true, [
                "verify"
            ]);
            const signaturePKCS1 = await crypto.subtle.sign({
                name: "RSASSA-PKCS1-v1_5",
                saltLength: 32
            }, privateKeyPKCS1, new Uint8Array([
                1,
                2,
                3,
                4
            ]));
            const verifyPKCS1 = await crypto.subtle.verify({
                name: "RSASSA-PKCS1-v1_5",
                saltLength: 32
            }, publicKeyPKCS1, signaturePKCS1, new Uint8Array([
                1,
                2,
                3,
                4
            ]));
            assert(verifyPKCS1);
        }
        for (const { hash , plainText  } of hashPlainTextVector){
            const hashMapOAEP: Record<string, string> = {
                "SHA-1": "RSA-OAEP",
                "SHA-256": "RSA-OAEP-256",
                "SHA-384": "RSA-OAEP-384",
                "SHA-512": "RSA-OAEP-512"
            };
            if (size == 1024 && hash == "SHA-512") {
                continue;
            }
            const encryptAlgorithm = {
                name: "RSA-OAEP"
            };
            const privateKeyOAEP = await crypto.subtle.importKey("jwk", {
                alg: hashMapOAEP[hash],
                ...privateJWK,
                ext: true,
                "key_ops": [
                    "decrypt"
                ]
            }, {
                ...encryptAlgorithm,
                hash
            }, true, [
                "decrypt"
            ]);
            const publicKeyOAEP = await crypto.subtle.importKey("jwk", {
                alg: hashMapOAEP[hash],
                ...publicJWK,
                ext: true,
                "key_ops": [
                    "encrypt"
                ]
            }, {
                ...encryptAlgorithm,
                hash
            }, true, [
                "encrypt"
            ]);
            const cipherText = await subtle.encrypt(encryptAlgorithm, publicKeyOAEP, plainText);
            assert(cipherText);
            assert(cipherText.byteLength > 0);
            assertEquals(cipherText.byteLength * 8, size);
            assert(cipherText instanceof ArrayBuffer);
            const decrypted = await subtle.decrypt(encryptAlgorithm, privateKeyOAEP, cipherText);
            assert(decrypted);
            assert(decrypted instanceof ArrayBuffer);
            assertEquals(new Uint8Array(decrypted), plainText);
        }
    }
});
const jwtECKeys = {
    "256": {
        size: 256,
        algo: "ES256",
        publicJWK: {
            kty: "EC",
            crv: "P-256",
            x: "0hCwpvnZ8BKGgFi0P6T0cQGFQ7ugDJJQ35JXwqyuXdE",
            y: "zgN1UtSBRQzjm00QlXAbF1v6s0uObAmeGPHBmDWDYeg"
        },
        privateJWK: {
            kty: "EC",
            crv: "P-256",
            x: "0hCwpvnZ8BKGgFi0P6T0cQGFQ7ugDJJQ35JXwqyuXdE",
            y: "zgN1UtSBRQzjm00QlXAbF1v6s0uObAmeGPHBmDWDYeg",
            d: "E9M6LVq_nPnrsh_4YNSu_m5W53eQ9N7ptAiE69M1ROo"
        }
    },
    "384": {
        size: 384,
        algo: "ES384",
        publicJWK: {
            kty: "EC",
            crv: "P-384",
            x: "IZwU1mYXs27G2IVrOFtzp000T9iude8EZDXdpU47RL1fvevR0I3Wni19wdwhjLQ1",
            y: "vSgTjMd4M3qEL2vWGyQOdCSfJGZ8KlgQp2v8KOAzX4imUB3sAZdtqFr7AIactqzo"
        },
        privateJWK: {
            kty: "EC",
            crv: "P-384",
            x: "IZwU1mYXs27G2IVrOFtzp000T9iude8EZDXdpU47RL1fvevR0I3Wni19wdwhjLQ1",
            y: "vSgTjMd4M3qEL2vWGyQOdCSfJGZ8KlgQp2v8KOAzX4imUB3sAZdtqFr7AIactqzo",
            d: "RTe1mQeE08LSLpao-S-hqkku6HPldqQVguFEGDyYiNEOa560ztSyzEAS5KxeqEBz"
        }
    }
};
type JWK = Record<string, string>;
function equalJwk(expected: JWK, got: JWK): boolean {
    const fields = Object.keys(expected);
    for(let i = 0; i < fields.length; i++){
        const fieldName = fields[i];
        if (!(fieldName in got)) {
            return false;
        }
        if (expected[fieldName] !== got[fieldName]) {
            return false;
        }
    }
    return true;
}
test(async function testImportExportEcDsaJwk() {
    const subtle = crypto.subtle;
    assert(subtle);
    for (const [_key, keyData] of Object.entries(jwtECKeys)){
        const { publicJWK , privateJWK , algo  } = keyData;
        const privateKeyECDSA = await subtle.importKey("jwk", {
            alg: algo,
            ...privateJWK,
            ext: true,
            "key_ops": [
                "sign"
            ]
        }, {
            name: "ECDSA",
            namedCurve: privateJWK.crv
        }, true, [
            "sign"
        ]);
        const expPrivateKeyJWK = await subtle.exportKey("jwk", privateKeyECDSA);
        assert(equalJwk(privateJWK, expPrivateKeyJWK as JWK));
        const publicKeyECDSA = await subtle.importKey("jwk", {
            alg: algo,
            ...publicJWK,
            ext: true,
            "key_ops": [
                "verify"
            ]
        }, {
            name: "ECDSA",
            namedCurve: publicJWK.crv
        }, true, [
            "verify"
        ]);
        const expPublicKeyJWK = await subtle.exportKey("jwk", publicKeyECDSA);
        assert(equalJwk(publicJWK, expPublicKeyJWK as JWK));
        const signatureECDSA = await subtle.sign({
            name: "ECDSA",
            hash: `SHA-${keyData.size}`
        }, privateKeyECDSA, new Uint8Array([
            1,
            2,
            3,
            4
        ]));
        const verifyECDSA = await subtle.verify({
            name: "ECDSA",
            hash: `SHA-${keyData.size}`
        }, publicKeyECDSA, signatureECDSA, new Uint8Array([
            1,
            2,
            3,
            4
        ]));
        assert(verifyECDSA);
    }
});
test(async function testImportEcDhJwk() {
    const subtle = crypto.subtle;
    assert(subtle);
    for (const [_key, jwkData] of Object.entries(jwtECKeys)){
        const { size , publicJWK , privateJWK  } = jwkData;
        const privateKeyECDH = await subtle.importKey("jwk", {
            ...privateJWK,
            ext: true,
            "key_ops": [
                "deriveBits"
            ]
        }, {
            name: "ECDH",
            namedCurve: privateJWK.crv
        }, true, [
            "deriveBits"
        ]);
        const expPrivateKeyJWK = await subtle.exportKey("jwk", privateKeyECDH);
        assert(equalJwk(privateJWK, expPrivateKeyJWK as JWK));
        const publicKeyECDH = await subtle.importKey("jwk", {
            ...publicJWK,
            ext: true,
            "key_ops": []
        }, {
            name: "ECDH",
            namedCurve: publicJWK.crv
        }, true, []);
        const expPublicKeyJWK = await subtle.exportKey("jwk", publicKeyECDH);
        assert(equalJwk(publicJWK, expPublicKeyJWK as JWK));
        const derivedKey = await subtle.deriveBits({
            name: "ECDH",
            public: publicKeyECDH
        }, privateKeyECDH, size);
        assert(derivedKey instanceof ArrayBuffer);
        assertEquals(derivedKey.byteLength, size / 8);
    }
});
const ecTestKeys = [
    {
        size: 256,
        namedCurve: "P-256",
        signatureLength: 64,
        raw: new Uint8Array([
            4,
            210,
            16,
            176,
            166,
            249,
            217,
            240,
            18,
            134,
            128,
            88,
            180,
            63,
            164,
            244,
            113,
            1,
            133,
            67,
            187,
            160,
            12,
            146,
            80,
            223,
            146,
            87,
            194,
            172,
            174,
            93,
            209,
            206,
            3,
            117,
            82,
            212,
            129,
            69,
            12,
            227,
            155,
            77,
            16,
            149,
            112,
            27,
            23,
            91,
            250,
            179,
            75,
            142,
            108,
            9,
            158,
            24,
            241,
            193,
            152,
            53,
            131,
            97,
            232
        ]),
        spki: new Uint8Array([
            48,
            89,
            48,
            19,
            6,
            7,
            42,
            134,
            72,
            206,
            61,
            2,
            1,
            6,
            8,
            42,
            134,
            72,
            206,
            61,
            3,
            1,
            7,
            3,
            66,
            0,
            4,
            210,
            16,
            176,
            166,
            249,
            217,
            240,
            18,
            134,
            128,
            88,
            180,
            63,
            164,
            244,
            113,
            1,
            133,
            67,
            187,
            160,
            12,
            146,
            80,
            223,
            146,
            87,
            194,
            172,
            174,
            93,
            209,
            206,
            3,
            117,
            82,
            212,
            129,
            69,
            12,
            227,
            155,
            77,
            16,
            149,
            112,
            27,
            23,
            91,
            250,
            179,
            75,
            142,
            108,
            9,
            158,
            24,
            241,
            193,
            152,
            53,
            131,
            97,
            232
        ]),
        pkcs8: new Uint8Array([
            48,
            129,
            135,
            2,
            1,
            0,
            48,
            19,
            6,
            7,
            42,
            134,
            72,
            206,
            61,
            2,
            1,
            6,
            8,
            42,
            134,
            72,
            206,
            61,
            3,
            1,
            7,
            4,
            109,
            48,
            107,
            2,
            1,
            1,
            4,
            32,
            19,
            211,
            58,
            45,
            90,
            191,
            156,
            249,
            235,
            178,
            31,
            248,
            96,
            212,
            174,
            254,
            110,
            86,
            231,
            119,
            144,
            244,
            222,
            233,
            180,
            8,
            132,
            235,
            211,
            53,
            68,
            234,
            161,
            68,
            3,
            66,
            0,
            4,
            210,
            16,
            176,
            166,
            249,
            217,
            240,
            18,
            134,
            128,
            88,
            180,
            63,
            164,
            244,
            113,
            1,
            133,
            67,
            187,
            160,
            12,
            146,
            80,
            223,
            146,
            87,
            194,
            172,
            174,
            93,
            209,
            206,
            3,
            117,
            82,
            212,
            129,
            69,
            12,
            227,
            155,
            77,
            16,
            149,
            112,
            27,
            23,
            91,
            250,
            179,
            75,
            142,
            108,
            9,
            158,
            24,
            241,
            193,
            152,
            53,
            131,
            97,
            232
        ])
    },
    {
        size: 384,
        namedCurve: "P-384",
        signatureLength: 96,
        raw: new Uint8Array([
            4,
            118,
            64,
            176,
            165,
            100,
            177,
            112,
            49,
            254,
            58,
            53,
            158,
            63,
            73,
            200,
            148,
            248,
            242,
            216,
            186,
            80,
            92,
            160,
            53,
            64,
            232,
            157,
            19,
            1,
            12,
            226,
            115,
            51,
            42,
            143,
            98,
            206,
            55,
            220,
            108,
            78,
            24,
            71,
            157,
            21,
            120,
            126,
            104,
            157,
            86,
            48,
            226,
            110,
            96,
            52,
            48,
            77,
            170,
            9,
            231,
            159,
            26,
            165,
            200,
            26,
            164,
            99,
            46,
            227,
            169,
            105,
            172,
            225,
            60,
            102,
            141,
            145,
            139,
            165,
            47,
            72,
            53,
            17,
            17,
            246,
            161,
            220,
            26,
            21,
            23,
            219,
            1,
            107,
            185,
            163,
            215
        ]),
        spki: new Uint8Array([
            48,
            118,
            48,
            16,
            6,
            7,
            42,
            134,
            72,
            206,
            61,
            2,
            1,
            6,
            5,
            43,
            129,
            4,
            0,
            34,
            3,
            98,
            0,
            4,
            118,
            64,
            176,
            165,
            100,
            177,
            112,
            49,
            254,
            58,
            53,
            158,
            63,
            73,
            200,
            148,
            248,
            242,
            216,
            186,
            80,
            92,
            160,
            53,
            64,
            232,
            157,
            19,
            1,
            12,
            226,
            115,
            51,
            42,
            143,
            98,
            206,
            55,
            220,
            108,
            78,
            24,
            71,
            157,
            21,
            120,
            126,
            104,
            157,
            86,
            48,
            226,
            110,
            96,
            52,
            48,
            77,
            170,
            9,
            231,
            159,
            26,
            165,
            200,
            26,
            164,
            99,
            46,
            227,
            169,
            105,
            172,
            225,
            60,
            102,
            141,
            145,
            139,
            165,
            47,
            72,
            53,
            17,
            17,
            246,
            161,
            220,
            26,
            21,
            23,
            219,
            1,
            107,
            185,
            163,
            215
        ]),
        pkcs8: new Uint8Array([
            48,
            129,
            182,
            2,
            1,
            0,
            48,
            16,
            6,
            7,
            42,
            134,
            72,
            206,
            61,
            2,
            1,
            6,
            5,
            43,
            129,
            4,
            0,
            34,
            4,
            129,
            158,
            48,
            129,
            155,
            2,
            1,
            1,
            4,
            48,
            202,
            7,
            195,
            169,
            124,
            170,
            81,
            169,
            253,
            127,
            56,
            28,
            98,
            90,
            255,
            165,
            72,
            142,
            133,
            138,
            237,
            200,
            176,
            92,
            179,
            192,
            83,
            28,
            47,
            118,
            157,
            152,
            47,
            65,
            133,
            140,
            50,
            83,
            182,
            191,
            224,
            96,
            216,
            179,
            59,
            150,
            15,
            233,
            161,
            100,
            3,
            98,
            0,
            4,
            118,
            64,
            176,
            165,
            100,
            177,
            112,
            49,
            254,
            58,
            53,
            158,
            63,
            73,
            200,
            148,
            248,
            242,
            216,
            186,
            80,
            92,
            160,
            53,
            64,
            232,
            157,
            19,
            1,
            12,
            226,
            115,
            51,
            42,
            143,
            98,
            206,
            55,
            220,
            108,
            78,
            24,
            71,
            157,
            21,
            120,
            126,
            104,
            157,
            86,
            48,
            226,
            110,
            96,
            52,
            48,
            77,
            170,
            9,
            231,
            159,
            26,
            165,
            200,
            26,
            164,
            99,
            46,
            227,
            169,
            105,
            172,
            225,
            60,
            102,
            141,
            145,
            139,
            165,
            47,
            72,
            53,
            17,
            17,
            246,
            161,
            220,
            26,
            21,
            23,
            219,
            1,
            107,
            185,
            163,
            215
        ])
    }
];
test(async function testImportEcSpkiPkcs8() {
    const subtle = window.crypto.subtle;
    assert(subtle);
    for (const { namedCurve , raw , spki , pkcs8 , signatureLength  } of ecTestKeys){
        const rawPublicKeyECDSA = await subtle.importKey("raw", raw, {
            name: "ECDSA",
            namedCurve
        }, true, [
            "verify"
        ]);
        const expPublicKeyRaw = await subtle.exportKey("raw", rawPublicKeyECDSA);
        assertEquals(new Uint8Array(expPublicKeyRaw), raw);
        const privateKeyECDSA = await subtle.importKey("pkcs8", pkcs8, {
            name: "ECDSA",
            namedCurve
        }, true, [
            "sign"
        ]);
        const expPrivateKeyPKCS8 = await subtle.exportKey("pkcs8", privateKeyECDSA);
        assertEquals(new Uint8Array(expPrivateKeyPKCS8), pkcs8);
        const expPrivateKeyJWK = await subtle.exportKey("jwk", privateKeyECDSA);
        assertEquals(expPrivateKeyJWK.crv, namedCurve);
        const publicKeyECDSA = await subtle.importKey("spki", spki, {
            name: "ECDSA",
            namedCurve
        }, true, [
            "verify"
        ]);
        const expPublicKeySPKI = await subtle.exportKey("spki", publicKeyECDSA);
        assertEquals(new Uint8Array(expPublicKeySPKI), spki);
        const expPublicKeyJWK = await subtle.exportKey("jwk", publicKeyECDSA);
        assertEquals(expPublicKeyJWK.crv, namedCurve);
        for (const hash of [
            "SHA-1",
            "SHA-256",
            "SHA-384",
            "SHA-512"
        ]){
            const signatureECDSA = await subtle.sign({
                name: "ECDSA",
                hash
            }, privateKeyECDSA, new Uint8Array([
                1,
                2,
                3,
                4
            ]));
            const verifyECDSA = await subtle.verify({
                name: "ECDSA",
                hash
            }, publicKeyECDSA, signatureECDSA, new Uint8Array([
                1,
                2,
                3,
                4
            ]));
            assert(verifyECDSA);
        }
    }
});
test(async function testAesGcmEncrypt() {
    const key = await crypto.subtle.importKey("raw", new Uint8Array(16), {
        name: "AES-GCM",
        length: 256
    }, true, [
        "encrypt",
        "decrypt"
    ]);
    const nonces = [
        {
            iv: new Uint8Array([
                0,
                1,
                2,
                3,
                4,
                5,
                6,
                7,
                8,
                9,
                10,
                11
            ]),
            ciphertext: new Uint8Array([
                50,
                223,
                112,
                178,
                166,
                156,
                255,
                110,
                125,
                138,
                95,
                141,
                82,
                47,
                14,
                164,
                134,
                247,
                22
            ])
        },
        {
            iv: new Uint8Array([
                0,
                1,
                2,
                3,
                4,
                5,
                6,
                7,
                8,
                9,
                10,
                11,
                12,
                13,
                14,
                15
            ]),
            ciphertext: new Uint8Array([
                210,
                101,
                81,
                216,
                151,
                9,
                192,
                197,
                62,
                254,
                28,
                132,
                89,
                106,
                40,
                29,
                175,
                232,
                201
            ])
        }
    ];
    for (const { iv , ciphertext: fixture  } of nonces){
        const data = new Uint8Array([
            1,
            2,
            3
        ]);
        const cipherText = await crypto.subtle.encrypt({
            name: "AES-GCM",
            iv
        }, key, data);
        assert(cipherText instanceof ArrayBuffer);
        assertEquals(cipherText.byteLength, 19);
        assertEquals(new Uint8Array(cipherText), fixture);
        const plainText = await crypto.subtle.decrypt({
            name: "AES-GCM",
            iv
        }, key, cipherText);
        assert(plainText instanceof ArrayBuffer);
        assertEquals(plainText.byteLength, 3);
        assertEquals(new Uint8Array(plainText), data);
    }
});
async function roundTripSecretJwk(jwk: JsonWebKey, algId: AlgorithmIdentifier | HmacImportParams, ops: KeyUsage[], validateKeys: (key: CryptoKey, originalJwk: JsonWebKey, exportedJwk: JsonWebKey) => void) {
    const key = await crypto.subtle.importKey("jwk", jwk, algId, true, ops);
    assert(key instanceof CryptoKey);
    assertEquals(key.type, "secret");
    const exportedKey = await crypto.subtle.exportKey("jwk", key);
    validateKeys(key, jwk, exportedKey);
}
test(async function testSecretJwkBase64Url() {
    const keyData = `{
      "kty": "oct",
      "k": "xxx",
      "alg": "HS512",
      "key_ops": ["sign", "verify"],
      "ext": true
    }`;
    await roundTripSecretJwk(JSON.parse(keyData), {
        name: "HMAC",
        hash: "SHA-512"
    }, [
        "sign",
        "verify"
    ], (key, _orig, exp)=>{
        assertEquals((key.algorithm as HmacKeyAlgorithm).length, 16);
        assertEquals(exp.k, "xxw");
    });
    await roundTripSecretJwk({
        kty: "oct",
        k: "HnZXRyDKn-_G5Fx4JWR1YA",
        alg: "HS256",
        "key_ops": [
            "sign",
            "verify"
        ],
        ext: true
    }, {
        name: "HMAC",
        hash: "SHA-256"
    }, [
        "sign",
        "verify"
    ], (key, orig, exp)=>{
        assertEquals((key.algorithm as HmacKeyAlgorithm).length, 128);
        assertEquals(orig.k, exp.k);
    });
    await roundTripSecretJwk({
        kty: "oct",
        k: "a-_AlFa-2-OmEGa_-z==",
        alg: "HS384",
        "key_ops": [
            "sign",
            "verify"
        ],
        ext: true
    }, {
        name: "HMAC",
        hash: "SHA-384"
    }, [
        "sign",
        "verify"
    ], (key, _orig, exp)=>{
        assertEquals((key.algorithm as HmacKeyAlgorithm).length, 104);
        assertEquals("a-_AlFa-2-OmEGa_-w", exp.k);
    });
    await roundTripSecretJwk({
        kty: "oct",
        k: "_u3K_gEjRWf-7cr-ASNFZw",
        alg: "A128CBC",
        "key_ops": [
            "encrypt",
            "decrypt"
        ],
        ext: true
    }, {
        name: "AES-CBC"
    }, [
        "encrypt",
        "decrypt"
    ], (_key, orig, exp)=>{
        assertEquals(orig.k, exp.k);
    });
    await roundTripSecretJwk({
        kty: "oct",
        k: "_____________________w==",
        alg: "A128CBC",
        "key_ops": [
            "encrypt",
            "decrypt"
        ],
        ext: true
    }, {
        name: "AES-CBC"
    }, [
        "encrypt",
        "decrypt"
    ], (_key, _orig, exp)=>{
        assertEquals(exp.k, "_____________________w");
    });
});
test(async function testAESWrapKey() {
    const key = await crypto.subtle.generateKey({
        name: "AES-KW",
        length: 128
    }, true, [
        "wrapKey",
        "unwrapKey"
    ]);
    const hmacKey = await crypto.subtle.generateKey({
        name: "HMAC",
        hash: "SHA-256",
        length: 128
    }, true, [
        "sign"
    ]);
    const wrappedKey = await crypto.subtle.wrapKey("raw", hmacKey, key, {
        name: "AES-KW"
    });
    assert(wrappedKey instanceof ArrayBuffer);
    assertEquals(wrappedKey.byteLength, 16 + 8);
    const unwrappedKey = await crypto.subtle.unwrapKey("raw", wrappedKey, key, {
        name: "AES-KW"
    }, {
        name: "HMAC",
        hash: "SHA-256"
    }, true, [
        "sign"
    ]);
    assert(unwrappedKey instanceof CryptoKey);
    assertEquals((unwrappedKey.algorithm as HmacKeyAlgorithm).length, 128);
    const hmacKeyBytes = await crypto.subtle.exportKey("raw", hmacKey);
    const unwrappedKeyBytes = await crypto.subtle.exportKey("raw", unwrappedKey);
    assertEquals(new Uint8Array(hmacKeyBytes), new Uint8Array(unwrappedKeyBytes));
});
test.ignore(async function testAesGcmTagLength() {
    const key = await crypto.subtle.importKey("raw", new Uint8Array(32), "AES-GCM", false, [
        "encrypt",
        "decrypt"
    ]);
    const iv = crypto.getRandomValues(new Uint8Array(12));
    const encrypted = await crypto.subtle.encrypt({
        name: "AES-GCM",
        iv,
        tagLength: 96
    }, key, new Uint8Array(32));
    await assertRejects(async ()=>{
        await crypto.subtle.decrypt({
            name: "AES-GCM",
            iv,
            tagLength: 96
        }, key, encrypted);
    });
});
test(async function ecPrivateKeyMaterialExportSpki() {
    const keys = await crypto.subtle.generateKey({
        name: "ECDSA",
        namedCurve: "P-256"
    }, true, [
        "sign",
        "verify"
    ]);
    assert(keys.privateKey instanceof CryptoKey);
    assert(keys.publicKey instanceof CryptoKey);
    const spki = await crypto.subtle.exportKey("spki", keys.publicKey);
    assert(spki instanceof ArrayBuffer);
});
test(async function importJwkWithUse() {
    const jwk = {
        "kty": "EC",
        "use": "sig",
        "crv": "P-256",
        "x": "FWZ9rSkLt6Dx9E3pxLybhdM6xgR5obGsj5_pqmnz5J4",
        "y": "_n8G69C-A2Xl4xUW2lF0i8ZGZnk_KPYrhv4GbTGu5G4"
    };
    const algorithm = {
        name: "ECDSA",
        namedCurve: "P-256"
    };
    const key = await crypto.subtle.importKey("jwk", jwk, algorithm, true, [
        "verify"
    ]);
    assert(key instanceof CryptoKey);
});
test(async function exportKeyNotExtractable() {
    const key = await crypto.subtle.generateKey({
        name: "HMAC",
        hash: "SHA-512"
    }, false, [
        "sign",
        "verify"
    ]);
    assert(key);
    assertEquals(key.extractable, false);
    await assertRejects(async ()=>{
        await crypto.subtle.exportKey("raw", key);
    }, DOMException);
});
test(async function testImportLeadingZeroesKey() {
    const alg = {
        name: "ECDSA",
        namedCurve: "P-256"
    };
    const jwk = {
        kty: "EC",
        crv: "P-256",
        alg: "ES256",
        x: "EvidcdFB1xC6tgfakqZsU9aIURxAJkcX62zHe1Nt6xU",
        y: "AHsk6BioGM7MZWeXOE_49AGmtuaXFT3Ill3DYtz9uYg",
        d: "WDeYo4o1heCF9l_2VIaClRyIeO16zsMlN8UG6Le9dU8",
        "key_ops": [
            "sign"
        ],
        ext: true
    };
    const key = await crypto.subtle.importKey("jwk", jwk, alg, true, [
        "sign"
    ]);
    assert(key instanceof CryptoKey);
    assertEquals(key.type, "private");
});
test(async function testECspkiRoundTrip() {
    const alg = {
        name: "ECDH",
        namedCurve: "P-256"
    };
    const { publicKey  } = await crypto.subtle.generateKey(alg, true, [
        "deriveBits"
    ]);
    const spki = await crypto.subtle.exportKey("spki", publicKey);
    await crypto.subtle.importKey("spki", spki, alg, true, []);
});
test(async function testHmacJwkImport() {
    await crypto.subtle.importKey("jwk", {
        kty: "oct",
        use: "sig",
        alg: "HS256",
        k: "hJtXIZ2uSN5kbQfbtTNWbpdmhkV8FJG-Onbc6mxCcYg"
    }, {
        name: "HMAC",
        hash: "SHA-256"
    }, false, [
        "sign",
        "verify"
    ]);
});
